﻿// (c) Copyright 2013 Mike Riedel.
// This source is subject to the Microsoft Public License (Ms-PL).
// All other rights reserved.

using FreshMeat.MiniHsm;

namespace FreshMeat.MiniHsmTest
{
   enum Badness
   {
      None = 0,
      TransitionDuringEntry,
      TransitionDuringInitial,
      TransitionDuringExit,
      TransitionDuringGetParent,
      ReturnNullFromGetParent,
   }

   class MockBadMachine : MiniMachine<MockBadMachine.Input>
   {
      public enum Input
      {
         GetParent = -4,
         SetDefault,
         Enter,
         Exit,
         Test
      }

      public Badness Badness;

      public MockBadMachine(Badness badness)
         : base(Input.GetParent, Input.SetDefault, Input.Enter, Input.Exit)
      {
         EnableValidation = true;
         Badness = badness;
         DefaultTo(A);
      }

      State A(Input input)
      {
         switch (input)
         {
            case Input.Enter:
               if (Badness == Badness.TransitionDuringEntry)
                  TransitionTo(B);
               return null;

            case Input.SetDefault:
               if (Badness == Badness.TransitionDuringInitial)
                  TransitionTo(B);
               return null;

            case Input.Exit:
               if (Badness == Badness.TransitionDuringExit)
                  TransitionTo(B);
               return null;

            case Input.Test:
               TransitionTo(B);
               return null;
         }

         if (input == Input.GetParent && Badness == Badness.TransitionDuringGetParent)
            TransitionTo(B);

         return input == Input.GetParent && Badness == Badness.ReturnNullFromGetParent ? (State)null : Root;
      }

      State B(Input input)
      {
         switch (input)
         {
            case Input.Enter:
               if (Badness == Badness.TransitionDuringEntry)
                  TransitionTo(A);
               return null;

            case Input.SetDefault:
               if (Badness == Badness.TransitionDuringInitial)
                  TransitionTo(A);
               return null;

            case Input.Exit:
               if (Badness == Badness.TransitionDuringExit)
                  TransitionTo(A);
               return null;

            case Input.Test:
               TransitionTo(A);
               return null;
         }

         if (input == Input.GetParent && Badness == Badness.TransitionDuringGetParent)
            TransitionTo(A);

         return input == Input.GetParent && Badness == Badness.ReturnNullFromGetParent ? (State)null : Root;
      }

      public void Update(Input input)
      {
         Process(input);
      }
   }
}
